/*
 * Commands.c
 *
 *  Created on: 3 mars 2012
 *      Author: Jeff
 */

#include <Arduino.h>
#include "ArgumentHandler.hpp"
#include "config.h"
#include "CommandHandler.hpp"
#include "IO.h"

CommandHandler::CommandHandler() {
	commands = NULL;
	commandCount = 0;
	argumentHdl = NULL;
}

void CommandHandler::registerArguments(ArgumentHandler * hdl) {
	argumentHdl = hdl;
}

void CommandHandler::registerAll(const struct CommandReference ** cmds, int cmdC) {
	commands = cmds;
	commandCount = cmdC;
}

int CommandHandler::matchCommand(char * query) {
	for (int i = 0; i < commandCount; i++) {
		byte * ptr = (byte *)(commands[i]);
		byte * str = (byte *)pgm_read_dword(ptr+2);

//		OUTPUT_PRINT("testing...");
//		OUTPUT_PRINTPGM((str));
//		OUTPUT_PRINT('\n');
		if (testStrings(query, str)) {
			return(i);
		}
	}
	return(255);
}

void CommandHandler::executeCommand(int cmd, struct CommandEnv * env) {
#ifdef SHELL_DEBUG
	OUTPUT_PRINT("executing command: ");
	OUTPUT_PRINTLN(cmd);
#endif
	if ((cmd < 0) || (cmd > commandCount)) {
		OUTPUT_PRINT("Internal Error, command does not exist");
		return;
	}
	byte * ptr = (byte *)(commands[cmd]);
//	byte * func = (byte *)pgm_read_dword(ptr+2);
	void (*process)(struct CommandEnv *) = (void (*)(struct CommandEnv *))pgm_read_dword(ptr);
	process(env);
}

boolean CommandHandler::parseCommandEnvironment(int cmd, char ** argStrings, struct CommandEnv * env) {
#ifdef SHELL_DEBUG
	OUTPUT_PRINTLN("CommandHandler::parseCommandEnvironment");
#endif
	for (int i=0; i<SHELL_ARGCOUNT_MAX; i++)
		env->arguments[i] = 0;

#ifdef SHELL_DEBUG
	OUTPUT_PRINT("command has ");
	OUTPUT_PRINT(commands[cmd].argCount);
	OUTPUT_PRINTLN(" arguments");
#endif
	byte * ptr = (byte *)(commands[cmd]);
	byte argC = pgm_read_byte(ptr+4);
	byte argT = -1;
	for (int i=0; i<argC; i++) {
#ifdef SHELL_DEBUG
		OUTPUT_PRINT("turning arg");
		OUTPUT_PRINT(i);
		OUTPUT_PRINT("into arg type ");
		OUTPUT_PRINT(commands[cmd].argTypes[i]);
#endif
		argT = pgm_read_byte(ptr+5+i);
		env->arguments[i] = argumentHdl->parseArgument(argT,argStrings[i]);
	}
	return(true);
}
